<template>
	<div>
		<!--面包屑，导航区域-->
		<el-breadcrumb separator="/">
			<el-breadcrumb-item :to="{ path: '/home' }">首页</el-breadcrumb-item>
			<el-breadcrumb-item>角色管理</el-breadcrumb-item>
			<el-breadcrumb-item>角色列表</el-breadcrumb-item>
		</el-breadcrumb>
		<!--主体数据区域-->
		<!--添加角色-->
		<el-card>
			<el-button type="primary" icon="el-icon-circle-plus-outline" @click="addRoledialog()">添加角色</el-button>
		</el-card>
		<el-card>
			<el-table :data="RoleList" style="width: 100%" border stripe>
				<el-table-column type="expand">
					<template v-slot="scope">
						<!--因为这里要使用索引变量,所以这里需要使用属性绑定-->
						<el-row v-for="(item1,i1) in scope.row.children" :key="item1.id" :class="[vcenter,bdbottom,i1 == 0 ? bdtop : '']">
							<!--渲染一级权限-->
							<el-col :span="5">
								<el-tag closable @close="removeRightById(scope.row,item1.id)">{{ item1.authName }}</el-tag>
								<i class="el-icon-caret-right"></i>
							</el-col>
							<!--渲染二级和三级权限-->
							<el-col :span="19">
								<!--通过for循环嵌套渲染二级权限-->
								<el-row v-for="(item2,i2) in item1.children" :key="item2.id" :class="[vcenter,i2 == 0 ? '' : bdtop]">
									<el-col :span="6">
										<el-tag type="success" closable @close="removeRightById(scope.row,item2.id);">{{ item2.authName }}</el-tag>
										<i class="el-icon-caret-right"></i>
									</el-col>
									<el-col :span="18">
										<el-tag closable class="three" type="warning" v-for="(item3,i3) in item2.children" :key="item3.id" @close="removeRightById(scope.row,item3.id)">{{ item3.authName }}</el-tag>
									</el-col>
								</el-row>
							</el-col>
						</el-row>
					</template>
				</el-table-column>
				<el-table-column type="index" label="#"></el-table-column>
				<el-table-column label="角色名称" prop="roleName"></el-table-column>
				<el-table-column label="角色描述" prop="roleDesc"></el-table-column>
				<el-table-column label="操作">
					<template slot-scope="scope">
						<el-button type="primary" icon="el-icon-edit" size="mini" @click="showEditDialog(scope.row.id)">编辑</el-button>
						<el-button type="danger" icon="el-icon-delete" size="mini" @click="removeRoleById(scope.row.id)">删除</el-button>
						<el-button type="warning" icon="el-icon-setting" size="mini" @click="showSetRightDialog(scope.row)">分配权限</el-button>
					</template>
				</el-table-column>
			</el-table>
		</el-card>

		<!--权限设置弹窗-->
		<el-dialog
		  title="提示"
		  :visible.sync="setRightdialogVisible"
		  width="30%"
		  @close="setRightdialogClose"
		  >
		  <el-tree :data="rightsList" :props="treeProps" show-checkbox default-expand-all node-key="id" :default-checked-keys="defKeys" ref="treeRef"></el-tree>
		  <span slot="footer" class="dialog-footer">
		    <el-button @click="setRightdialogVisible = false">取 消</el-button>
		    <el-button type="primary" @click="allotRights">确 定</el-button>
		  </span>
		</el-dialog>

		<!--添加角色弹窗-->
		<el-dialog
				title="添加角色"
				:visible.sync="addRoledialogVisible"
				width="30%"
				>
			<el-form ref="addFormRef" :model="addForm" :rules="addFormRules" label-width="80px">
				<el-form-item label="角色名称" prop="roleName">
					<el-input v-model="addForm.roleName"></el-input>
				</el-form-item>
				<el-form-item label="角色描述" prop="roleDesc">
					<el-input v-model="addForm.roleDesc"></el-input>
				</el-form-item>
			</el-form>
			<span slot="footer" class="dialog-footer">
			<el-button @click="addRoledialogVisible = false">取 消</el-button>
			<el-button type="primary" @click="addRole">确 定</el-button>
		  </span>
		</el-dialog>

		<!--修改角色弹窗-->
		<el-dialog title="修改角色" :visible.sync="editDialogVisible" width="30%">
			<el-form ref="editFormRef" :model="editForm" :rules="editFormRules" label-width="80px">
				<el-form-item label="角色名称" prop="roleName">
					<el-input v-model="editForm.roleName"></el-input>
				</el-form-item>
				<el-form-item label="角色描述" prop="roleDesc">
					<el-input v-model="editForm.roleDesc"></el-input>
				</el-form-item>
			</el-form>
			<span slot="footer" class="dialog-footer">
			<el-button @click="editDialogVisible = false">取 消</el-button>
			<el-button type="primary" @click="editRole">确 定</el-button>
			</span>
		</el-dialog>

	</div>
</template>

<script type="text/javascript">
	export default{
		data(){
			return {
				RoleList : [],
				bdbottom : 'bdbottom',
				bdtop : 'bdtop',
				vcenter : 'vcenter',
				setRightdialogVisible : false,
				editDialogVisible : false,
				rightsList : [],//权限树数据
				roleId : '',//当前的角色id
				//树状结构的 props
				treeProps : {
					children : 'children',//默认子节点的字段
					label : 'authName' //显示节点的字段
				},
				//默认选中的权限
				defKeys : [],
				addRoledialogVisible : false,
				//添加角色的模型
				addForm:{
					roleName : '',
					roleDesc : ''
				},
				//修改角色模型
				editForm : {

				},
				//添加表单验证规则
				addFormRules:{
					roleName : [
						{ required : true , message : '请输入角色名称',trigger : 'blur' },
						{ min : 2, max : 10 , message: '名称在2-10位之间' ,trigger : 'blur' }
					],
					roleDesc : [
						{ required: true , message : '请输入角色描述',trigger : 'blur' },
						{ min : 1 , max : 15 , message: '描述在1-15位之间' , trigger : 'blur' }
					]
				},
				//修改表单验证规则
				editFormRules: {
					roleName : [
						{ required : true , message : '请输入角色名称',trigger : 'blur' },
						{ min : 2, max : 10 , message: '名称在2-10位之间' ,trigger : 'blur' }
					],
					roleDesc : [
						{ required: true , message : '请输入角色描述',trigger : 'blur' },
						{ min : 1 , max : 15 , message: '描述在1-15位之间' , trigger : 'blur' }
					]
				}
			}
		},
		created() {
			this.getRoleList()
		},
		methods:{
			async getRoleList(){
				const {data : res} = await this.$http.get('roles');
				this.RoleList = res.data;
			},
			//role 角色信息  rightId 权限id
			async removeRightById(role,rightId){
				const confirmResult =  await this.$confirm('此操作将永久删除该权限, 是否继续?', '提示', {
				  confirmButtonText: '确定',
				  cancelButtonText: '取消',
				  type: 'warning'
				}).catch(err => err);
				if(confirmResult != 'confirm'){
					return this.$message.warning('已经取消删除权限');
				}
				//如果点击了确定按钮的话,就调取接口
				const {data : res} = await this.$http.delete(`roles/${role.id}/rights/${rightId}`);
				if(res.meta.status != 200){
					return this.$message.error('删除权限失败');
				}
				this.$message.success('删除权限成功');
				//删除成功之后将最新的权限赋值给当前角色
				//无需重载所有的权限，只需要当前角色的信息进行重载即可
				role.children = res.data;
			},
			//分配权限弹窗
			async showSetRightDialog(role){
				this.setRightdialogVisible = true;
				//保存当前角色的id
				this.roleId = role.id;
				//获取权限树数据
				const {data : res} = await this.$http.get('rights/tree');
				if(res.meta.status != 200){
					return this.$message.error('获取权限树失败');
				}
				this.rightsList = res.data;
				//调用getLeafKeys进行递归,将三级权限添加到数组中
				this.getLeafKeys(role,this.defKeys);
			},
			//给角色分配权限
			async allotRights(){
				//当用户在树形权限对话框中点击确定，将用户选择的权限发送请求进行更新
				//获取所有选中以及半选中的内容
				//getCheckedKeys 若节点可以被选择(即返回目前被选中的全节点的key所组成的数组)
				//getHalfCheckedKeys 若节点可以被选择 (即返回目前被选中的半节点的key所组成的数组)
				const keys = [
					...this.$refs.treeRef.getCheckedKeys(),
					...this.$refs.treeRef.getHalfCheckedKeys()
				];
				//将数组转化为 , 拼接的字符串
				const idStr = keys.join(',');
				//发送请求完成更新
				const {data : res} = await this.$http.post(`roles/${this.roleId}/rights`,{rids : idStr});
				if(res.meta.status != 200){
					return this.$message.error('权限分配失败');
				}
				this.$message.success('权限分配成功');
				//分配成功之后,关闭弹窗
				this.setRightdialogVisible = false;
				this.getRoleList();
			},
			//获取所有的已经选择的权限
			getLeafKeys(node,arr){
				//该函数会获取到当前角色的所有的三级权限id并添加到defKeys中
				//如果当前的节点不包含children属性,则表示node为三级权限
				if(!node.children){
					return arr.push(node.id);
				}
				//如果当前的节点是有children节点的，则表示是有子节点的，那么这个时候就应该使用递归进行调用了
				node.children.forEach(item => {
					this.getLeafKeys(item,arr);
				});
			},
			//关闭的时候清空数据
			setRightdialogClose(){
				this.defKeys = [];
			},
			//添加叫角色页面
			addRoledialog(){
				this.addRoledialogVisible = true;
			},
			//添加角色操作
			addRole(){
				//先对表单进行验证
				this.$refs.addFormRef.validate(async valid => {
					if(!valid){
						return this.$message.error('请填写完整的信息');
					}
					//信息填写完整之后调用接口
					const {data : res} =  await this.$http.post('roles',this.addForm);
					if(res.meta.status != 201){
						return this.$message.error('角色添加失败');
					}
					//如果添加成功了,就进行刷新
					this.$message.success('添加角色成功');
					this.getRoleList();
					this.addRoledialogVisible = false;
				});
			},
			//修改角色弹窗
			async showEditDialog(id){
				this.editDialogVisible = true;
				//通过id查询出当前角色的信息
				const {data : res} = await this.$http.get('roles/'+id);
				if(res.meta.status != 200){
					return this.$message.error('获取角色信息失败');
				}
				//获取成功之后,将数据进行填充
				this.editForm = res.data;
			},
			editRole(){
				this.$refs.editFormRef.validate(async valid => {
					if(!valid){
						return this.$message.error('请填写完整的信息');
					}
					//如果全部验证通过了,就调取接口
					const {data : res} = await this.$http.put('roles/'+this.editForm.roleId,{roleName:this.editForm.roleName,roleDesc:this.editForm.roleDesc});
					if(res.meta.status != 200){
						return this.$message.error('修改角色信息失败');
					}
					this.$message.success('角色信息修改成功');
					//修改成功之后关闭弹窗
					this.editDialogVisible = false;
					//刷新当前的角色列表
					this.getRoleList();
				});
			},
			//删除角色信息
			async removeRoleById(id){
				const confirmResult = await this.$confirm('此操作会将角色彻底删除,是否继续?','提示',{
					confirmButtonText : '确定',
					cancelButtonText : '取消',
					type : 'warning'
				}).catch(err => err);
				if(confirmResult != 'confirm'){
					return this.$message.error('取消了删除操作');
				}
				//进行删除操作
				const {data : res} = await this.$http.delete('roles/'+id);
				if(res.meta.status != 200){
					return this.$message.error('删除失败');
				}
				this.$message.success('删除成功');
				this.getRoleList();
			}


		}
	}
</script>



<style scoped="scoped">
	.el-card{
		margin-top: 7px;
	}
	.el-row{
		padding-top: 5px;
		padding-bottom: 5px;
		margin-top: 7px;
	}
	.bdbottom{
		border-bottom: 1px solid #DDDDDD;
	}
	.bdtop{
		border-top: 1px solid #DDDDDD;
	}
	.three{
		margin-left: 15px;
	}
	.vcenter{
		display: flex;
		align-items: center;
	}

</style>
